package org.rsbot.script.wrappers;

import java.awt.Point;
import java.awt.Polygon;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import org.rsbot.client.Model;
import org.rsbot.script.methods.Calculations;
import org.rsbot.script.methods.Menu;
import org.rsbot.script.methods.MethodContext;
import org.rsbot.script.methods.MethodProvider;
import org.rsbot.script.methods.Mouse;
import org.rsbot.script.util.Filter;

public abstract class RSModel extends MethodProvider
{
  protected int[] xPoints;
  protected int[] yPoints;
  protected int[] zPoints;
  protected short[] indices1;
  protected short[] indices2;
  protected short[] indices3;

  public static Filter<RSModel> newVertexFilter(short[] paramArrayOfShort)
  {
    return new Filter(paramArrayOfShort)
    {
      public boolean accept(RSModel paramRSModel) {
        return Arrays.equals(paramRSModel.indices1, this.val$vertex_a);
      }
    };
  }

  public RSModel(MethodContext paramMethodContext, Model paramModel)
  {
    super(paramMethodContext);
    this.xPoints = paramModel.getXPoints();
    this.yPoints = paramModel.getYPoints();
    this.zPoints = paramModel.getZPoints();
    this.indices1 = paramModel.getIndices1();
    this.indices2 = paramModel.getIndices2();
    this.indices3 = paramModel.getIndices3();
  }

  protected abstract int getLocalX();

  protected abstract int getLocalY();

  protected abstract void update();

  private boolean contains(Point paramPoint)
  {
    if (this == null) {
      return false;
    }
    Polygon[] arrayOfPolygon1 = getTriangles();
    for (Polygon localPolygon : arrayOfPolygon1) {
      if (localPolygon.contains(paramPoint))
        return true;
    }
    return false;
  }

  public boolean doClick(boolean paramBoolean)
  {
    try
    {
      for (int i = 0; i < 10; i++) {
        this.methods.mouse.move(getPoint());
        if (contains(this.methods.mouse.getLocation())) {
          this.methods.mouse.click(paramBoolean);
          return true;
        }
      }
    } catch (Exception localException) {
    }
    return false;
  }

  public boolean doAction(String paramString)
  {
    try
    {
      for (int i = 0; i < 10; i++) {
        this.methods.mouse.move(getPoint());
        if ((contains(this.methods.mouse.getLocation())) && 
          (this.methods.menu.contains(paramString)) && 
          (this.methods.menu.doAction(paramString))) {
          return true;
        }
      }

    }
    catch (Exception localException)
    {
    }

    return false;
  }

  public Point getPoint()
  {
    update();
    int i = this.indices1.length;
    int j = random(0, i);
    Point localPoint = getPointInRange(j, i);
    if (localPoint != null) {
      return localPoint;
    }
    localPoint = getPointInRange(0, j);
    if (localPoint != null) {
      return localPoint;
    }
    return new Point(-1, -1);
  }

  public Point[] getPoints()
  {
    if (this == null)
      return null;
    Polygon[] arrayOfPolygon1 = getTriangles();
    Point[] arrayOfPoint = new Point[arrayOfPolygon1.length * 3];
    int i = 0;
    for (Polygon localPolygon : arrayOfPolygon1) {
      for (int m = 0; m < 3; m++)
        arrayOfPoint[(i++)] = new Point(localPolygon.xpoints[m], localPolygon.ypoints[m]);
    }
    return arrayOfPoint;
  }

  public Point getPointOnScreen()
  {
    ArrayList localArrayList = new ArrayList();
    try {
      Polygon[] arrayOfPolygon = getTriangles();
      for (int i = 0; i < arrayOfPolygon.length; i++) {
        Polygon localPolygon = arrayOfPolygon[i];
        for (int j = 0; j < localPolygon.xpoints.length; j++) {
          Point localPoint = new Point(localPolygon.xpoints[j], localPolygon.ypoints[j]);
          if (this.methods.calc.pointOnScreen(localPoint)) {
            return localPoint;
          }
          localArrayList.add(localPoint);
        }
      }
    }
    catch (Exception localException) {
    }
    return localArrayList.size() > 0 ? (Point)localArrayList.get(random(0, localArrayList.size())) : null;
  }

  public Point getCentralPoint()
  {
    try
    {
      int i = 0; int j = 0; int k = 0;
      for (Object localObject3 : getTriangles()) {
        for (int i1 = 0; i1 < localObject3.npoints; i1++) {
          i += localObject3.xpoints[i1];
          j += localObject3.ypoints[i1];
          k++;
        }
      }
      ??? = new Point(i / k, j / k);

      Object localObject2 = null;
      double d1 = 20000.0D;
      for (Polygon localPolygon : getTriangles()) {
        for (int i4 = 0; i4 < localPolygon.npoints; i4++) {
          Point localPoint = new Point(localPolygon.xpoints[i4], localPolygon.ypoints[i4]);
          if (!this.methods.calc.pointOnScreen(localPoint))
            continue;
          double d2 = this.methods.calc.distanceBetween((Point)???, localPoint);
          if ((localObject2 == null) || (d2 < d1)) {
            localObject2 = localPoint;
            d1 = d2;
          }
        }
      }
      return localObject2;
    } catch (Exception localException) {
    }
    return (Point)new Point(-1, -1);
  }

  public Polygon[] getTriangles()
  {
    update();
    LinkedList localLinkedList = new LinkedList();
    int i = getLocalX();
    int j = getLocalY();
    int k = this.indices1.length;
    int m = this.methods.calc.tileHeight(i, j);
    for (int n = 0; n < k; n++) {
      Point localPoint1 = this.methods.calc.worldToScreen(i + this.xPoints[this.indices1[n]], j + this.zPoints[this.indices1[n]], m + this.yPoints[this.indices1[n]]);

      Point localPoint2 = this.methods.calc.worldToScreen(i + this.xPoints[this.indices2[n]], j + this.zPoints[this.indices2[n]], m + this.yPoints[this.indices2[n]]);

      Point localPoint3 = this.methods.calc.worldToScreen(i + this.xPoints[this.indices3[n]], j + this.zPoints[this.indices3[n]], m + this.yPoints[this.indices3[n]]);

      if ((localPoint1.x >= 0) && (localPoint2.x >= 0) && (localPoint3.x >= 0)) {
        localLinkedList.add(new Polygon(new int[] { localPoint1.x, localPoint2.x, localPoint3.x }, new int[] { localPoint1.y, localPoint2.y, localPoint3.y }, 3));
      }
    }

    return (Polygon[])localLinkedList.toArray(new Polygon[localLinkedList.size()]);
  }

  public void hover()
  {
    this.methods.mouse.move(getPoint());
  }

  public boolean equals(Object paramObject)
  {
    if ((paramObject instanceof RSModel)) {
      RSModel localRSModel = (RSModel)paramObject;
      return (Arrays.equals(this.indices1, localRSModel.indices1)) && (Arrays.equals(this.xPoints, localRSModel.xPoints)) && (Arrays.equals(this.yPoints, localRSModel.yPoints)) && (Arrays.equals(this.zPoints, localRSModel.zPoints));
    }

    return false;
  }

  private Point getPointInRange(int paramInt1, int paramInt2) {
    int i = getLocalX();
    int j = getLocalY();
    int k = this.methods.calc.tileHeight(i, j);
    for (int m = paramInt1; m < paramInt2; m++) {
      Point localPoint1 = this.methods.calc.worldToScreen(i + this.xPoints[this.indices1[m]], j + this.zPoints[this.indices1[m]], k + this.yPoints[this.indices1[m]]);

      int n = -1; int i1 = -1;
      if (localPoint1.x >= 0) {
        n = localPoint1.x;
        i1 = localPoint1.y;
      }
      Point localPoint2 = this.methods.calc.worldToScreen(i + this.xPoints[this.indices2[m]], j + this.zPoints[this.indices2[m]], k + this.yPoints[this.indices2[m]]);

      if (localPoint2.x >= 0) {
        if (n >= 0) {
          n = (n + localPoint2.x) / 2;
          i1 = (i1 + localPoint2.y) / 2;
        } else {
          n = localPoint2.x;
          i1 = localPoint2.y;
        }
      }
      Point localPoint3 = this.methods.calc.worldToScreen(i + this.xPoints[this.indices3[m]], j + this.zPoints[this.indices3[m]], k + this.yPoints[this.indices3[m]]);

      if (localPoint3.x >= 0) {
        if (n >= 0) {
          n = (n + localPoint3.x) / 2;
          i1 = (i1 + localPoint3.y) / 2;
        } else {
          n = localPoint3.x;
          i1 = localPoint3.y;
        }
      }
      if (n >= 0) {
        return new Point(n, i1);
      }
    }
    return null;
  }
}